package org.icnmasjid.member.webapp.action;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.icnmasjid.member.model.Person;
import org.icnmasjid.member.model.Role;
import org.icnmasjid.member.model.SubOrg;
import org.icnmasjid.member.service.LookupManager;
import org.icnmasjid.member.service.PersonManager;
import org.icnmasjid.member.util.CommonUtil;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;

import com.google.gdata.client.appsforyourdomain.AppsGroupsService;
import com.google.gdata.data.appsforyourdomain.AppsForYourDomainErrorCode;
import com.google.gdata.data.appsforyourdomain.AppsForYourDomainException;
import com.google.gdata.data.appsforyourdomain.generic.GenericEntry;
import com.google.gdata.data.appsforyourdomain.generic.GenericFeed;

public class SyncMailingListsWithGoogle extends BaseFormController {

	private PersonManager personManager;
	private LookupManager lookupManager;

    public SyncMailingListsWithGoogle() {
    	setCommandClass(Person.class);
    	setCommandName("person");
	}
    
	private AppsGroupsService groupService;    

    @Override
    protected boolean isFormSubmission(HttpServletRequest request) {
    	return true;
    }
    
    private void syncWithGoogle(List<String> emailList, String mailingList) throws Exception {
    	// get all the members from google
    	List<String> emailListFromGoogle = getEmailListFromGoogle(mailingList);
    	System.out.println("Mailist List: " + mailingList);
    	System.out.println("Email List: " + emailList.toString());
    	Set<String> newEmails = new HashSet<String>(emailList);
    	newEmails.removeAll(emailListFromGoogle);
    	// lets add two emails to this
    	//newEmails.add("admin@icnschool.com");
    	newEmails.add("email_approvers@icnschool.com");
    	System.out.println("newEmails: " + newEmails.toString());    	
    	addEmailListToGoogle(newEmails, mailingList);
    	
    	Set<String> deletedEmails = new HashSet<String>(emailListFromGoogle);
    	deletedEmails.removeAll(emailList);
    	//deletedEmails.remove("admin@icnschool.com");
    	deletedEmails.remove("email_approvers@icnschool.com");
    	System.out.println("deletedEmails: " + deletedEmails.toString());    	
    	removeEmailListFromGoogle(deletedEmails, mailingList);
    }
    
    
    private void addEmailListToGoogle(Collection<String> col, String mailingList) throws Exception{
    	for (String email : col) {
    		try {
    			groupService.addMemberToGroup(mailingList, email);
    		} catch (AppsForYourDomainException e) {
    		    if (e.getErrorCode() == AppsForYourDomainErrorCode.EntityDoesNotExist ) {
    		        e.printStackTrace();
    		        try {
    		        	CommonUtil.send("registrations@icnschool.com", "email missing: " + email, email);
    		        } catch (MessagingException me) {
    		        	me.printStackTrace();
    		        }
    		    }
    		}

    	}
    }
    
    private void removeEmailListFromGoogle(Collection<String> col, String mailingList) throws Exception{
    	for (String email : col) {
    		groupService.deleteMemberFromGroup(mailingList, email);
    	}
    }
    
    
    private List<String> getEmailListFromGoogle(String mailingList) throws Exception {
        List<String> members = new ArrayList<String>();
        GenericFeed groupsFeed = groupService.retrieveAllMembers(mailingList);
        do {
	        Iterator<GenericEntry> groupsEntryIterator = groupsFeed.getEntries().iterator();
	        while (groupsEntryIterator.hasNext()) {
	          members.add(groupsEntryIterator.next().getProperty(AppsGroupsService.APPS_PROP_GROUP_MEMBER_ID).toLowerCase());
	        }
	        if ( groupsFeed.getNextLink() != null) {
	        	groupsFeed = groupService.getNextPage(groupsFeed.getNextLink());
	        } else {
	        	groupsFeed = null;
	        }
        } while (groupsFeed != null);
        return members;
    }
    
    

    public ModelAndView onSubmit(HttpServletRequest request,
                                 HttpServletResponse response, Object command,
                                 BindException errors)
    throws Exception {
    	if ( !request.getParameterMap().containsKey("password")) {
    		throw new IllegalArgumentException("password must be specified");
    	}
    	String password = request.getParameter("password");
    	groupService = new AppsGroupsService("icnschool@icnschool.com", password, "icnschool.com", "icnmember");
        if (log.isDebugEnabled()) {
            log.debug("entering 'onSubmit' method...");
        }        
        Role role = lookupManager.getRoleByName("Student-2014");
        // get the list of grades
        List<SubOrg> list = lookupManager.getObjects(SubOrg.class);
        List<String> masterList = new ArrayList<String>();
        // loop thru each grade
        for ( SubOrg so: list ) {
        	List<Person> persons = personManager.getParents(so, role);
        	System.out.println(so.getName());
        	System.out.println(so.getMailingList());
        	System.out.println(persons.size());
        	// for each mailing list create an list of emails
        	// im only interested in grades with mailing lists
        	if ( StringUtils.isNotBlank(so.getMailingList()) ) {
        		List<String> emailList = new ArrayList<String>();
        		for (Person p: persons) {
        			if ( StringUtils.isNotBlank(p.getEmail() )) {
        				emailList.add(p.getEmail().toLowerCase());
        			}
        			
        			if ( StringUtils.isNotBlank(p.getEmail2() )) {
        				emailList.add(p.getEmail2().toLowerCase());
        			}
        			
        			if ( p.getSpouse() != null ) {
            			if ( StringUtils.isNotBlank(p.getSpouse().getEmail() )) {
            				emailList.add(p.getSpouse().getEmail().toLowerCase());
            			}
            			
            			if ( StringUtils.isNotBlank(p.getSpouse().getEmail2() )) {
            				emailList.add(p.getSpouse().getEmail2().toLowerCase());
            			}        				
        			}        			
        		} // end for
        		syncWithGoogle(emailList, so.getMailingList()+"@icnschool.com");
        		masterList.addAll(emailList);
        	}
        }        
        syncWithGoogle(masterList, "parents2014@icnschool.com");
        return new ModelAndView("importReport");
    }

	public LookupManager getLookupManager() {
		return lookupManager;
	}

	public void setLookupManager(LookupManager lookupManager) {
		this.lookupManager = lookupManager;
	}

	public PersonManager getPersonManager() {
		return personManager;
	}
	
    public void setPersonManager(PersonManager personManager) {
        this.personManager = personManager;
    }
	

}
